package main

import (
	"fmt"
	"sync"
	"time"
)

type Task struct {
	ID     int
	Status string
}

type TaskManager struct {
	tasks    map[int]*Task
	mutex    sync.Mutex
	stopChan chan struct{}
}

func NewTaskManager() *TaskManager {
	return &TaskManager{
		tasks:    make(map[int]*Task),
		stopChan: make(chan struct{}),
	}
}

func (tm *TaskManager) AddTask(id int) {
	tm.mutex.Lock()
	defer tm.mutex.Unlock()

	if _, ok := tm.tasks[id]; ok {
		fmt.Println("Task already exists")
		return
	}

	tm.tasks[id] = &Task{
		ID:     id,
		Status: "active",
	}
	fmt.Println("Task added:", id)
}

func (tm *TaskManager) CancelTask(id int) {
	tm.mutex.Lock()
	defer tm.mutex.Unlock()

	if task, ok := tm.tasks[id]; ok {
		task.Status = "canceled"
		fmt.Println("Task canceled:", id)
	} else {
		fmt.Println("Task not found")
	}
}

func (tm *TaskManager) ExecuteTask(id int) {
	tm.mutex.Lock()
	defer tm.mutex.Unlock()

	// for {
	if task, ok := tm.tasks[id]; ok {
		task.Status = "executing"
		fmt.Println("Executing task:", id)
		// Call your method or function here
		// For example: YourMethod()
		time.Sleep(3 * time.Second) // Simulating task execution time
		task.Status = "completed"
		fmt.Println("Task completed:", id)
	} else {
		fmt.Println("Task not found")
	}
	// }

}

func (tm *TaskManager) MonitorTasks() {
	for {
		select {
		case <-tm.stopChan:
			return
		default:
			tm.printTasks()
			time.Sleep(time.Second) // Print task status every second
		}
	}
}

func (tm *TaskManager) StopMonitoring() {
	tm.stopChan <- struct{}{}
}

func (tm *TaskManager) printTasks() {
	tm.mutex.Lock()
	defer tm.mutex.Unlock()

	fmt.Println("Current tasks:")
	for _, task := range tm.tasks {
		fmt.Printf("Task ID: %d, Status: %s\n", task.ID, task.Status)
	}
}

func main() {
	taskManager := NewTaskManager()

	go taskManager.MonitorTasks()

	taskManager.AddTask(1)
	// taskManager.AddTask(2)

	// time.Sleep(2 * time.Second)

	// taskManager.ExecuteTask(1)

	// time.Sleep(5 * time.Second)

	// taskManager.CancelTask(2)

	// time.Sleep(3 * time.Second)

	// taskManager.StopMonitoring()

}
